﻿using System;
using System.Reflection;
using System.Collections.Generic;

namespace Caramel.Entities.Testing
{
	public abstract class Property<T> where T : class, IEntity, new()
	{
		public string Name { get { return this.Member.Name; } }

		protected PropertyInfo Member { get; set; }

		public Func<T, object> ValueFactory { get; set; }

		public void SetValue(T entity)
		{
			try
			{
				this.Member.SetValue(entity, this.ValueFactory(entity), null);
			}
			catch (Exception e)
			{
				throw new ArgumentException(String.Format("Unable to set value for '{0}': {1}", this.Name, e.Message), e);
			}
		}

		public object GetValue(T entity)
		{
			return this.Member.GetValue(entity, null);
		}

		public abstract void CheckValue(T expected, T actual);
	}

	public abstract class Property<T, TProperty> : Property<T> where T : class, IEntity, new()
    {
		protected Property(PropertyInfo member, Func<TProperty, TProperty, bool> comparer)
		{
			this.Member = member;
			this.Comparer = comparer;
		}

		protected Func<TProperty, TProperty, bool> Comparer { get; private set; }
    }
}
